09 性能优化面试题
1、如何降低Token成本?
降低 Token 成本,核心是减少无效输入和无效输出。
大模型调用通常按输入 Token 和输出 Token 计费,所以优化时要从两边一起看。
第一,精简 System Prompt。
很多系统提示词越写越长,里面有不少重复、空泛或者已经由代码保证的规则。比如权限校验、字段校验这些最好放在程序里,不要都靠 Prompt 描述。
第二,减少无关上下文。
不要把所有历史对话、所有文档、所有记忆都塞进 Prompt。应该按需召回,只放当前问题真正需要的内容。
第三,做会话摘要。
长对话可以把早期内容压缩成摘要,只保留最近几轮原文。
早期 30 轮对话 -> 一段摘要
最近 5 轮对话 -> 原文保留第四,控制 RAG 的 TopK。
RAG 召回太多文档,会大量增加输入 Token。可以先召回较多候选,再通过 Rerank 只放最相关的几段进入 Prompt。
第五,限制输出长度。
如果业务只需要结论,就不要让模型输出长篇解释。
请用 3 条以内回答,每条不超过 50 字。第六,小模型处理简单任务。
分类、抽取、格式转换、意图识别这类任务,不一定都用最强模型。可以用更便宜的模型处理,复杂推理再交给强模型。
第七,能用代码做的不要交给模型。
排序、过滤、去重、JSON 校验、权限判断等确定性逻辑,用代码更便宜也更稳定。
在 LangChain v1.0 / LangGraph v1.0 中,可以把复杂 Agent 拆成多个节点,不同节点使用不同模型。比如意图识别节点用低成本模型,最终回答节点再用高质量模型。
2、如何降低接口延迟?
接口延迟主要来自几部分:模型推理、Prompt 长度、工具调用、网络请求、检索和排队。
降低延迟要先拆开看,不要只盯着模型。
第一,减少 Prompt 长度。
输入越长,模型处理越慢。精简系统提示词、减少无关历史、控制 RAG 文档数量,都会降低延迟。
第二,控制输出长度。
输出越长,生成时间越长。如果只需要结论,就明确限制输出。
第三,使用流式输出。
流式输出不能减少总耗时,但可以缩短首字时间,让用户更快看到响应。
第四,并行执行独立任务。
如果一个问题需要同时查多个数据源,能并行就不要串行。
串行:查A -> 查B -> 查C
并行:同时查A、B、C -> 汇总第五,缓存重复结果。
相同问题、相同检索结果、相同工具返回,可以适当缓存,减少重复调用。
第六,优化工具超时。
外部 API 慢是 Agent 延迟的重要来源。每个工具都要设置超时时间,不能无限等待。
第七,使用合适的模型。
简单任务不要用大模型,复杂任务才用高能力模型。
在 LangGraph v1.0 中,可以把独立节点并行执行,再用汇总节点合并结果。这样比所有步骤都放在一个 Agent 循环里更容易控制延迟。
3、如何提高Agent响应速度?
Agent 响应慢,通常不是单一原因,而是 LLM 调用多、工具调用慢、流程太长、检索内容太多共同造成的。
可以从几个方向优化。
第一,减少不必要的 Agent 循环。
有些任务只需要一次模型调用,却被设计成“思考 -> 调工具 -> 再思考 -> 再调工具”。要判断哪些场景可以直接回答,哪些场景才需要多步执行。
第二,提前做意图判断。
先判断用户请求类型。如果只是闲聊或普通解释,不需要走完整 RAG 或工具链。
第三,工具并行化。
多个互不依赖的工具可以并行调用,比如同时查订单、物流、售后记录。
第四,缓存中间结果。
检索结果、Embedding、用户画像、热点文档都可以缓存。
第五,减少上下文传递。
每个步骤只传需要的信息,不要把整个历史状态都塞给每个节点。
第六,使用流式输出。
用户感知速度往往比总耗时更重要。先输出“正在查询订单”,再流式返回结果,体验会好很多。
第七,拆分工作流。
在 LangGraph v1.0 里,可以用图结构把 Agent 拆成多个节点:意图识别、检索、工具调用、回答生成。简单路径走短流程,复杂路径才走完整流程。
示例:
用户输入
↓
意图识别
├── 普通知识问答 -> 直接回答
├── 文档问答 -> RAG 检索后回答
└── 业务操作 -> 调工具后回答这样可以避免所有请求都走最重的流程。
4、如何提高系统并发能力?
提高并发能力,核心是减少阻塞、合理限流、横向扩展,并保护下游服务。
第一,使用异步 IO。
Agent 经常要调用模型、数据库、搜索服务、外部 API,这些都是 IO 密集型操作。用异步方式可以减少线程阻塞。
第二,连接池管理。
数据库、Redis、HTTP 客户端都要使用连接池,避免每次请求都新建连接。
第三,模型调用限流。
模型服务通常有 QPS、RPM、TPM 限制。系统要根据模型供应商限制做队列和限流,不能无限并发打过去。
第四,工具隔离。
不同工具的并发限制应该分开配置。比如搜索服务最多 50 并发,支付服务最多 5 并发,不能共用一个大池子。
第五,任务队列。
耗时任务不要都同步处理,可以放到队列里异步执行。用户先拿到任务 ID,再查询结果。
第六,横向扩展。
Agent 服务本身尽量设计成无状态,状态放到 Redis、数据库或 LangGraph checkpointer / store 中,这样可以多实例部署。
第七,缓存热点数据。
热点文档、用户画像、系统配置可以缓存,减少数据库压力。
在 LangGraph v1.0 中,如果使用持久化 checkpointer,要注意后端存储的并发能力。Agent 服务可以横向扩展,但状态存储、向量库、模型 API 都可能成为瓶颈。
5、如何做缓存设计?
Agent 系统里的缓存要分层设计,不能只做一个简单的 key-value 缓存。
常见缓存有几类。
第一,Prompt 或回答缓存。
对于完全相同的问题和上下文,可以缓存最终答案。但这种缓存要谨慎,因为用户、权限、时间、知识库版本不同,答案可能不同。
第二,RAG 检索缓存。
相同 query 的检索结果可以缓存一段时间,尤其是热点问题。
第三,Embedding 缓存。
同一段文本生成 embedding 的结果可以缓存,避免重复调用 embedding 模型。
第四,工具结果缓存。
比如天气、汇率、商品信息、配置查询,可以按业务设置 TTL。
第五,用户画像缓存。
用户偏好、权限、组织信息读取频繁,可以缓存到 Redis。
设计缓存 key 时,要把影响结果的因素都放进去:
user_id
query
model
prompt_version
knowledge_base_version
permission_scope否则容易出现缓存污染,比如 A 用户看到 B 用户的数据。
缓存还要考虑失效策略:
固定 TTL
数据更新时主动失效
按版本号隔离
手动清理在 RAG 场景里,比较稳的做法是用 knowledge_base_version 作为缓存 key 的一部分。文档更新后版本变化,旧缓存自然不再命中。
6、如何设计限流机制?
限流的目的是保护系统和下游服务,避免请求过多导致整体不可用。
Agent 系统里通常需要多层限流。
第一,用户级限流。
限制单个用户单位时间内的请求数,防止恶意刷接口或误操作。
每个用户每分钟最多 20 次请求第二,租户级限流。
SaaS 场景下,一个企业客户不能占满全部资源。
每个租户每分钟最多 1000 次请求第三,模型级限流。
不同模型有不同 RPM、TPM 限制,需要按模型分别控制。
第四,工具级限流。
外部 API、搜索服务、数据库都要有自己的限流策略。
第五,任务级限流。
对于高成本任务,比如长文档分析、批量生成、复杂 Agent 流程,要限制并发数量。
常见算法包括:
- 固定窗口
- 滑动窗口
- 令牌桶
- 漏桶
实际项目中,令牌桶比较常用,因为它允许短时间突发,但整体速率可控。
限流后的处理也很重要。不要让请求一直阻塞,可以返回明确提示:
当前请求较多,请稍后重试。或者进入队列,异步处理。
7、如何设计熔断机制?
熔断机制是为了防止下游服务异常时,把整个系统拖垮。
比如模型服务大量超时、向量数据库不可用、某个第三方 API 持续报错,如果系统还不断请求它,就会造成线程堆积、请求变慢,甚至整体雪崩。
熔断一般有三种状态。
Closed:正常请求
Open:熔断打开,直接拒绝或走降级
Half-Open:放少量请求试探服务是否恢复触发熔断的条件可以是:
- 连续失败次数超过阈值
- 错误率超过阈值
- 平均延迟超过阈值
- 超时请求过多
例如:
1分钟内错误率超过 50%,并且请求数超过 100,打开熔断 30 秒熔断后要有降级策略:
- 模型不可用:切换备用模型
- RAG 不可用:提示知识库暂时不可用
- 工具不可用:返回稍后重试
- 实时数据不可用:使用缓存数据并标明时间
Agent 系统里要特别注意工具熔断。一个工具不可用,不应该影响所有 Agent 能力。比如天气工具挂了,知识库问答仍然应该正常。
8、如何监控Agent运行状态?
监控 Agent 运行状态,要看模型、工具、流程、业务结果四个层面。
第一,模型层指标。
包括:
- 请求量
- 成功率
- 平均延迟
- 首 Token 延迟
- 输入 Token 数
- 输出 Token 数
- 错误类型
- 模型供应商状态
第二,工具层指标。
包括每个工具的调用次数、成功率、超时率、平均耗时、错误原因。
第三,流程层指标。
Agent 一次任务可能有多步,需要统计:
- 平均步骤数
- 最大步骤数
- 每个节点耗时
- 卡在哪个节点
- 是否触发重试
- 是否触发人工确认
第四,业务层指标。
比如:
- 用户是否解决问题
- 点赞 / 点踩
- 追问率
- 转人工率
- 工单关闭率
只看技术指标不够。一个 Agent 即使调用成功率很高,也可能回答没用。
在 LangChain / LangGraph 项目中,通常会结合 LangSmith 做链路观测,记录每次 LLM 调用、工具调用、节点输入输出和耗时。生产环境也可以把关键指标打到 Prometheus、Grafana、ELK 或 OpenTelemetry 系统里。
9、如何统计Token消耗?
Token 消耗通常要按请求、用户、租户、模型、业务场景几个维度统计。
每次模型调用后,都要记录:
{
"model": "claude-sonnet-4-5",
"input_tokens": 1200,
"output_tokens": 300,
"total_tokens": 1500,
"user_id": "u_001",
"tenant_id": "t_001",
"trace_id": "trace_001",
"scene": "rag_qa"
}统计 Token 的目的有几个。
第一,成本核算。
知道每个用户、每个租户、每个功能花了多少钱。
第二,发现异常。
如果某个接口 Token 突然暴涨,可能是 Prompt 变长、检索内容过多,或者出现循环调用。
第三,优化依据。
比如发现 RAG 问答中输入 Token 占 90%,就应该优化检索内容和 Prompt,而不是只盯着输出。
第四,配额控制。
可以按用户或租户设置每日 Token 上限,超过后限流或降级。
在 LangChain v1.0 中,可以通过回调、middleware 或 tracing 记录模型调用用量。在 LangGraph v1.0 中,可以在每个调用模型的节点记录 usage,并把它和 trace_id 关联起来。
10、如何统计Tool调用成功率?
Tool 调用成功率是判断 Agent 稳定性的重要指标。
每次工具调用都应该记录:
{
"tool_name": "search_docs",
"success": true,
"duration_ms": 320,
"error_type": null,
"retry_count": 0,
"trace_id": "trace_001"
}统计时通常看几个指标:
- 调用次数
- 成功次数
- 失败次数
- 成功率
- 超时率
- 平均耗时
- P95 / P99 耗时
- 重试次数
- 失败原因分布
成功率计算很简单:
Tool成功率 = 成功调用次数 / 总调用次数但要注意区分失败类型。
比如:
参数错误:可能是 Tool Schema 或 Prompt 问题
权限错误:可能是用户无权限或校验正常拦截
网络超时:可能是下游服务问题
返回为空:可能是数据不存在,不一定是系统错误不要把所有失败都简单算成“工具不好用”。
在 LangGraph 中,如果工具执行放在 ToolNode 或独立节点里,可以统一做日志、重试、耗时统计和错误分类。
11、如何统计Agent成功率?
Agent 成功率比 Tool 成功率更复杂,因为 Agent 的“成功”不只是接口返回 200。
要先定义什么叫成功。
常见定义有几种。
第一,技术成功。
Agent 流程正常结束,没有异常、没有超时、没有超过最大步数。
第二,任务成功。
Agent 完成了用户目标,比如查到了订单、生成了报告、完成了分类。
第三,答案成功。
回答正确、完整、没有编造,用户能接受。
第四,业务成功。
比如客服场景中,用户没有转人工,问题被解决;销售场景中,用户完成下一步动作。
不同场景要用不同指标。
可以记录:
{
"trace_id": "trace_001",
"agent_name": "customer_service_agent",
"status": "success",
"finish_reason": "completed",
"steps": 4,
"duration_ms": 5600,
"user_feedback": "thumb_up"
}常见统计指标包括:
- 流程完成率
- 超时率
- 最大步数中断率
- 工具失败导致的失败率
- 用户满意率
- 转人工率
- 追问率
在 Agent 系统中,最好把失败原因分类清楚:
模型理解失败
工具调用失败
检索无结果
权限不足
用户信息不完整
流程超时
人工拒绝这样后续才能知道该优化 Prompt、工具、RAG,还是业务流程。
12、如何定位Agent故障?
定位 Agent 故障,不能只看最终报错,要还原整条执行链路。
一般按下面顺序排查。
第一,看用户输入。
问题是否清楚?是否缺少必要信息?是否包含歧义?
第二,看 Prompt。
System Prompt 和当前上下文是否正确?有没有冲突指令?有没有把错误记忆或错误文档放进去?
第三,看模型输出。
模型是直接回答了,还是决定调用工具?如果调用工具,工具名和参数是否正确?
第四,看工具执行。
工具是否超时?参数是否校验失败?下游接口是否返回异常?
第五,看 RAG 检索。
如果是知识库问答,要看检索到了哪些 Chunk,正确资料有没有召回,Rerank 是否把正确内容排前面。
第六,看状态流转。
Agent 是否进入错误分支?是否循环调用?是否超过最大步数?
第七,看最终输出。
模型是否基于工具结果回答?有没有忽略关键结果?有没有编造?
所以故障定位需要完整 trace,而不是只记录最后一句回答。
在 LangGraph v1.0 中,每个节点的输入、输出、耗时和异常都应该可观察。这样定位问题时可以直接看到是卡在检索、工具、模型,还是状态路由。
13、如何做Agent链路追踪?
Agent 链路追踪的目标,是把一次用户请求中发生的所有步骤串起来。
每次请求应该有一个全局 trace_id,每个步骤有自己的 span_id。
一条链路可能包括:
用户请求
↓
LLM 调用:意图识别
↓
RAG 检索
↓
Rerank
↓
Tool 调用
↓
LLM 调用:生成最终答案每个 span 要记录:
{
"trace_id": "trace_001",
"span_id": "span_002",
"name": "search_docs",
"type": "tool",
"start_time": "...",
"end_time": "...",
"duration_ms": 320,
"status": "success",
"input": {},
"output": {},
"error": null
}链路追踪可以帮助回答几个问题:
- 慢在哪里
- 错在哪里
- 调用了哪些工具
- 检索到了哪些文档
- Token 花在哪里
- 为什么生成这个答案
在 LangChain / LangGraph 中,可以使用 LangSmith 做 tracing。它可以记录 Agent 的每一步执行,包括模型输入输出、工具调用、节点状态和耗时。
如果公司已有观测系统,也可以接 OpenTelemetry,把 Agent trace 和后端服务 trace 串起来。这样就能从一次用户请求追到数据库、搜索服务、模型服务和第三方 API。
14、如何处理模型服务不可用?
模型服务不可用时,不能让整个系统直接崩掉,需要有降级方案。
常见处理方式有几个。
第一,设置超时。
模型调用必须设置超时时间,不能一直等待。
第二,重试。
对临时性错误可以重试,比如网络抖动、限流后的短暂失败。但重试要有限制,并使用指数退避,避免把供应商打得更慢。
第三,切换备用模型。
如果主模型不可用,可以切到备用模型。比如主模型负责高质量回答,备用模型负责基础问答或简单任务。
第四,降级回答。
如果模型完全不可用,可以返回明确提示:
当前智能助手服务暂时不可用,请稍后重试。对于部分业务,可以退回规则模板或搜索结果摘要。
第五,排队处理。
如果是批处理任务,可以先进入队列,等模型恢复后继续执行。
第六,熔断。
如果模型服务持续失败,要打开熔断,短时间内不再继续请求,避免请求堆积。
第七,告警。
模型不可用要及时通知运维或值班人员,并记录影响范围。
在 LangGraph v1.0 中,可以把模型调用节点包装成带重试、熔断和 fallback 的节点。失败后通过条件边路由到备用模型节点或降级节点。
15、如何设计高可用架构?
Agent 高可用架构要避免单点故障,并保证核心链路在部分组件失败时还能降级运行。
一个比较常见的架构是:
入口网关
↓
Agent 服务集群
↓
状态存储 / Redis / 数据库 / 向量库
↓
模型供应商 / 工具服务 / 业务系统关键设计点有几个。
第一,Agent 服务无状态化。
服务实例本身不要保存关键状态。会话状态、长期记忆、任务状态要放到外部存储,这样实例挂了可以由其他实例接管。
在 LangGraph v1.0 中,checkpointer 和 store 应该使用可持久化后端,而不是只用内存版本。
第二,多实例部署。
Agent 服务至少部署多个副本,通过负载均衡分发请求。
第三,核心存储高可用。
Redis、数据库、向量库都要考虑主从、集群、备份和恢复。否则 Agent 服务再多,状态存储挂了也不可用。
第四,模型服务多供应商或多模型备份。
主模型不可用时,可以切换备用模型。不同任务也可以使用不同模型,降低单一模型故障影响。
第五,限流、熔断、降级。
高可用不是永远不失败,而是失败时能控制影响范围。模型、工具、向量库、第三方 API 都应该有熔断和降级策略。
第六,队列削峰。
高峰期或大任务可以进入消息队列异步处理,避免同步接口被打满。
第七,完整监控和告警。
要监控请求量、延迟、错误率、Token 消耗、工具成功率、模型可用性、队列积压、存储状态等。
第八,数据隔离和权限控制。
多租户系统要避免缓存、记忆、向量检索串租户。高可用不能以牺牲数据安全为代价。
整体上,Agent 高可用架构不是只把服务多部署几台,而是要让模型、工具、记忆、检索、状态流转这些关键环节都具备容错能力。